/*
 * Copyright 2013 floreysoft GmbH (www.floreysoft.net)
 *
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.floreysoft.gwt.drive.client.realtime;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;

/**
 * The collaborative model is the data model for a Realtime document. The
 * document's object graph should be added to the model under the root object.
 * All objects that are part of the model must be accessible from this root.
 * 
 * The model class is also used to create instances of built in and custom
 * collaborative objects via the appropriate create method.
 * 
 * Listen on the model for the following events:
 * 
 * gapi.drive.realtime.EventType.UNDO_REDO_STATE_CHANGED
 * 
 * This class should not be instantiated directly. The collaborative model is
 * generated during the document load process. The model can be initialized by
 * passing an initializer function to gapi.drive.realtime.load.
 * 
 * 
 */
public final class Model extends EventTarget {

	protected Model() {
	}

	/**
	 * @return True if the model can currently redo.
	 */
	public native boolean canRedo()/*-{
		return !!this.canRedo;
	}-*/;

	/**
	 * @return True if the model can currently undo.
	 */
	public native boolean canUndo()/*-{
		return !!this.canUndo;
	}-*/;

	/**
	 * Starts a compound operation. If a name is given, that name will be
	 * recorded in the mutation for use in revision history, undo menus, etc.
	 * When beginCompoundOperation() is called, all subsequent edits to the data
	 * model will be batched together in the undo stack and revision history
	 * until endCompoundOperation() is called. Compound operations may be nested
	 * inside other compound operations. Note that the compound operation MUST
	 * start and end in the same synchronous execution block. If this invariant
	 * is violated, the data model will become invalid and all future changes
	 * will fail.
	 * 
	 */
	public native void beginCompoundOperation(String opt_name)/*-{
		this.beginCompoundOperation(opt_name);
	}-*/;

	/**
	 * Ends a compound operation. This method will throw an exception if no
	 * compound operation is in progress.
	 */
	public native void endCompoundOperation() /*-{
		this.endCompoundOperation();
	}-*/;

	/**
	 * Creates a collaborative string.
	 * 
	 * @param opt_initialValue
	 *            Sets the initial value for this string.
	 * @return {@link CollaborativeString} A collaborative string.
	 */
	public native CollaborativeString createString(String opt_initialValue)/*-{
		return this.createString(opt_initialValue);
	}-*/;

	/**
	 * Creates a collaborative string.
	 * 
	 * @return {@link CollaborativeString} A collaborative string.
	 */
	public native CollaborativeString createString()/*-{
		return this.createString();
	}-*/;

	/**
	 * Creates a collaborative list.
	 * 
	 * @param value
	 *            Initial value for the list.
	 * @return {@link CollaborativeList} A collaborative list.
	 */
	public native <T extends JavaScriptObject> CollaborativeList<T> createList(JsArray<T> value)/*-{
		return this.createList(value);
	}-*/;

	/**
	 * Creates a collaborative list.
	 * 
	 * @return {@link CollaborativeList} A collaborative list.
	 */
	public native <T> CollaborativeList<T> createList()/*-{
		return this.createList();
	}-*/;

	/**
	 * Creates a collaborative map.
	 * 
	 * @return {@link CollaborativeMap} A collaborative map.
	 */
	public native <T> CollaborativeMap<T> createMap()/*-{
		return this.createMap();
	}-*/;

	/**
	 * Returns the root of the object model.
	 * 
	 * @return {@link CollaborativeMap} The root of the object model.
	 */
	public native <T> CollaborativeMap<T> getRoot()/*-{
		return this.getRoot();
	}-*/;

	/**
	 * Redo the last thing the active collaborator undid.
	 */
	public native void redo()/*-{
		this.redo();
	}-*/;

	/**
	 * Undo the last thing the active collaborator did.
	 */
	public native void undo()/*-{
		this.undo();
	}-*/;
}
